package it.scambiocorse.dao;

import it.scambiocorse.model.AreaType;
import it.scambiocorse.model.ClienteType;
import it.scambiocorse.model.CodaType;
import it.scambiocorse.model.IdentificativoType;
import it.scambiocorse.model.ServizioType;
import it.scambiocorse.model.UtenteType;
import it.scambiocorse.rowmapper.AreaRowMapper;
import it.scambiocorse.rowmapper.ClientiRowMapper;
import it.scambiocorse.rowmapper.ServizioRowMapper;
import it.scambiocorse.rowmapper.UtenteRowMapper;
import it.scambiocorse.utils.Costanti;
import it.scambiocorse.utils.Utils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
import org.springframework.transaction.annotation.Transactional;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;

public class UtenteDao extends JdbcDaoSupport implements UtenteService  {

		
		final Logger logger = Logger.getLogger(getClass());

	  protected void initDao() throws Exception {
	    super.initDao();
	    getJdbcTemplate().setNativeJdbcExtractor(new SimpleNativeJdbcExtractor());

	  }
	  
		public UtenteType getUser(int idUser) throws Exception {
			String metodo = "getUser(...) - ";
			logger.warn(metodo+" - Inizio");
		  ResultSet rs = null; 
		  UtenteType ret = null;
		  String sql = "SELECT * FROM utente_tab where id_user = ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
		  	ret = (UtenteType) getJdbcTemplate().queryForObject(sql, new Object[] { idUser }, new UtenteRowMapper());
		  	logger.warn(metodo+" Esito: OK, utente estratto "+ret.getLogin());
		  // Do whatever I want with resultset here... 
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
		}


		
		public ArrayList<UtenteType> getUsersPerCode(ArrayList<CodaType> listaCode) {
			ArrayList<UtenteType> userList = null;
			String in = "";
			 for (int i = 0;i < userList.size();i++) {
				 UtenteType u = userList.get(i);
				 in+=""+u.getIdUser();
				 if (i != (userList.size()-1)) {
					 in+=",";
				 }
			 }
			 
			return userList;
		}

//		public int inserisciUtente(UtenteType utente) throws Exception {
//			String metodo = "inserisciCliente(...) - ";
//			logger.warn(metodo+"Inizio");
//			
//		  int ret = 0;
//		  String sql = "INSERT INTO utente_tab VALUES(?,?,?,?,?,?,?,?,?,?)";
//		  try{ 
//			  PreparedStatementCreator
//		  	ret = getJdbcTemplate().queryForInt(sql, new Object[]{utente.getIdUser(), utente.getLogin(), utente.getNome(), utente.getCognome(), utente.getRagiSoci(),
//		  									utente.getPass(), utente.getNote(), Utils.getSysDate(), Utils.dataStringTimestamp(Costanti.DATA_FINE, "dd/MM/yyyy"), 0});
//		  	logger.warn(metodo+" - Chiamata SQL = "+sql);
//		  	logger.warn(metodo+"ID_USER estratto: "+ret);
//		
//		  
//		  logger.warn(metodo+" Fine");
//		  
////
//		  	if (ret > 0) {
//		  		logger.warn(metodo+" Esito: OK, utente INSERITO, idCliente = "+ret);
//		  	} else {
//		  		logger.warn(metodo+" Attenzione: cliente NON INSERITO");
//		  	}
//		  	
//		  } catch (Exception e) {
//		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
//		  	logger.error(e);
//		  	throw e;
//		  }
//		  
//		  
//		  logger.warn(metodo+" Fine");	
//			return ret;
//
//		}
		
		@Transactional
		public int inserisciUtente(UtenteType u) throws Exception {
			String metodo = "inserisciUtente(...) - ";
			logger.warn(metodo+"Inizio");
		  Number idUser = 0;
		  String sql = "INSERT INTO utente_tab(login,nome,cogn,ragi_soci,ret,note,data_iniz, data_fine, email, activation) "+
				  "VALUES (?,?,?,?,?,?,?,?,?,?);";
		  
		  //"VALUES (login, nome,cognome,ragiSoci,pwd,note,NOW(),STR_TO_DATE('31/12/9999', '%d/%m/%Y'), email, activation);";
		  try{ 

			  Object[] params = new Object[] { u.getLogin(),u.getNome(),u.getCognome(), u.getRagiSoci(),Utils.toMd5(u.getPass()),u.getNote(),Utils.getSysDate(),
					  			Utils.dataStringTimestamp(Costanti.DATA_FINE,  Costanti.DATA_PATTERN), u.getEmail(),u.getActivation() };
			  
			 idUser = getJdbcTemplate().update(sql, params);
			 
			 
//		  	idUser = caller.executeFunction(Number.class, getUtenteParams(utente));

		  	if (idUser.intValue() > 0) {
		  		idUser = getJdbcTemplate().queryForInt( "select last_insert_id()" );
		  		logger.warn(metodo+" Esito: OK, utente INSERITO, idUser = "+idUser.intValue());
		  	} else {
		  		logger.warn(metodo+" Attenzione: utente NON INSERITO");
		  		throw new Exception("Utente non inserito");
		  	}
		  	
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		return idUser.intValue();				
		}


		private Map getUtenteParams(UtenteType utente) {
			Map ret = new HashMap<String,Object>();
			ret.put("login", utente.getNome()+" "+utente.getCognome());
			ret.put("nome", utente.getNome());
			ret.put("cognome", utente.getCognome());
			ret.put("ragiSoci", utente.getRagiSoci());
			ret.put("pwd", Utils.toMd5(utente.getPass()));
			ret.put("note", utente.getNote());
			ret.put("email", utente.getEmail());
			ret.put("activation", utente.getActivation());


			return ret;
		}
		
		public int getIdUserDaLogin(String login) throws Exception {
			String metodo = "esisteLogin(...)";
			logger.warn(metodo+" - Inizio");
		  int ret = 0;
		  String sql = "SELECT ID_USER FROM utente_tab where login= ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+login);
		  	ret = getJdbcTemplate().queryForInt(sql, new Object[] { login });
		  	logger.warn(metodo+"Il LOGIN E' "+((ret == 0) ? "LIBERO" : "GIA' ASSEGNATO"));

		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
			
		}
//
//		public void completaRegistrazione(UtenteType utente) {
//			//TODO  
//		}

		public int getIdIdesFromDescValoIdes(String descValoIdes) throws Exception {
			String metodo = "getIdIdesFromDescValoIdes(...)";
			logger.warn(metodo+" - Inizio");
		  int ret = 0;
		  String sql = "SELECT ID_IDES FROM ides_tab where desc_valo_ides = ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+descValoIdes);
		  	ret = getJdbcTemplate().queryForInt(sql, new Object[] { descValoIdes });
		  	logger.warn(metodo+"QUESTO CAP E' "+((ret == 0) ? "LIBERO" : "GIA' ASSEGNATO"));
		  // Do whatever I want with resultset here... 
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
			
		}

		public void inserisciIdes(IdentificativoType ides) throws Exception {
			String metodo = "inserisciIdes(...) - ";
			logger.warn(metodo+"Inizio");
		  Number idIdes;
		  String sql = "call inserisciIdes(?,?,?,?,?,?)";
		  try{ 
		  	
		  	SimpleJdbcCall caller = new SimpleJdbcCall(getJdbcTemplate())
		  	.withFunctionName("inserisciIdes");
		  	
		  	idIdes = caller.executeFunction(Number.class, getIdesParams(ides));

		  	if (idIdes.intValue() > 0) {
		  		logger.warn(metodo+" Esito: OK, identificativo INSERITO, idIdes = "+idIdes.intValue());
		  	} else {
		  		logger.warn(metodo+" Attenzione: identificativo NON INSERITO");
		  	}
		  	
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");				
		}

		private Map getIdesParams(IdentificativoType ides) {
				Map ret = new HashMap<String,Object>();
				if (ides.getIdUser() != 0) 
					ret.put("id_ides", ides.getIdIdes());
				ret.put("id_user", ides.getIdUser());
				ret.put("tipo_ides", ides.getTipoIdes());
				ret.put("desc_valo_ides", ides.getDescValoIdes());
				ret.put("data_iniz", ides.getDataIniz());
				ret.put("data_fine", ides.getDataFine());
				ret.put("docu_scan", ides.getDocuScan());
				
				return ret;
		}

		public int getIdUserDaCodiFisc(String codiFisc) throws Exception {
			String metodo = "getIdUserDaCodiFisc(...) - ";
			logger.warn(metodo+" - Inizio");
		  int ret = 0;
		  String sql = "SELECT ID_USER FROM utente_tab where codi_fisc = ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+codiFisc);
		  	ret = getJdbcTemplate().queryForInt(sql, new Object[] { codiFisc });
		  	logger.warn(metodo+"ID_USER estratto: "+ret);
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
		}

		public int getIdUserDaEmail(String email) throws Exception {
			String metodo = "getIdUserDaEmail(...) - ";
			logger.warn(metodo+" - Inizio");
		  int ret = 0;
		  String sql = "SELECT ID_USER FROM utente_tab where email = ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+email);
		  	ret = getJdbcTemplate().queryForInt(sql, new Object[] { email });
		  	logger.warn(metodo+"ID_USER estratto: "+ret);
		  } catch (EmptyResultDataAccessException em) {
			  logger.warn(metodo+"Utente non trovato");
		  }
		  catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
		}
		
		
		public UtenteType login(String email, String pass) throws Exception {
			String metodo = "login(...) - ";
			logger.warn(metodo+" - Inizio");
		  UtenteType ret = null;
		  pass = Utils.toMd5(pass);
		  String sql = "SELECT * FROM utente_tab where email = ? and ret = ? ";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+pass);
		  	ret = (UtenteType) getJdbcTemplate().queryForObject(sql, new Object[] {email, pass }, new UtenteRowMapper());
		  	logger.warn(metodo+" Esito: OK, utente estratto "+ret.getLogin());
		  } catch (EmptyResultDataAccessException em) {
			  logger.warn(metodo+"Utente non trovato");
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  	throw e;
		  }
		  
		  logger.warn(metodo+" Fine");
		  
			return ret;
		}

		@Transactional
		public boolean attivaUtente(int idUser, String activation)		throws Exception {
			String metodo = "login(...) - ";
			logger.warn(metodo+" - Inizio");
			int ret = 0;
			boolean check = false;
			
			  String sql = "UPDATE utente_tab SET activation = NULL where id_user = ? and activation = ?  ";
			  try{ 
			  	
			  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+activation+" ? ="+idUser);
			  	ret = getJdbcTemplate().update(sql, new Object[] {idUser, activation});
			  	
			  	if (ret > 0) {
			  		logger.warn(metodo+" ATTIVAZIONE RIUSCITA");
			  		check = true;
			  	} else {
			  		logger.warn(metodo+" ATTIVAZIONE NON RIUSCITA");
			  	}
			  	
			  
			  } catch (Exception e) {
			  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
			  	logger.error(e);
			  	throw e;
			  }
			  
			  logger.warn(metodo+" Fine");			
			
			
			return check;
		}		
		
		
		
	
}
